﻿using CL_VisionCommu_Test.Helper;
using CL_VisionCommu_Test.Models;
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using static CL_VisionCommu_Test.Helper.Helper;
using MessageBox = System.Windows.Forms.MessageBox;
using ImTools;
using System.Windows.Input;
using System.Windows.Data;
using System.Globalization;
using System.Windows.Controls;
using MahApps.Metro.Controls;
using System.Windows;
using DryIoc;
using static System.Net.WebRequestMethods;
using System.Threading;
using System.Diagnostics;
using CL_VisionCommu_Test.UserDefControl;
using CL_VisionCommu_Test.Device;

namespace CL_VisionCommu_Test.ViewModels
{
    internal class MultiValueConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            return values.ToArray();
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    public class MainWindowViewModel : BindableBase
    {
        #region 属性字段
        /// <summary>
        /// Master/Slave
        /// </summary>
        private int commnuMode = 0;
        private bool tsPlatForm = false;
        private int managerNameIndex = 0;
        private string configFilePath = null;
        private string connectedstring = "";



        private bool  _server;

        public bool Server
        {
            get => _server;
            set { SetProperty(ref _server, value); }
        }

        private bool _client;

        public bool Client
        {
            get => _client;
            set { SetProperty(ref _client, value); }
        }

        public bool TsPlatForm 
        { 
            get => tsPlatForm;
            set{ SetProperty(ref tsPlatForm , value); }
        }

        public string ConnectedString
        {
            get => connectedstring;
            set { SetProperty(ref connectedstring, value); }
        }
        // Model
        private MainWindowModel model;

        public MainWindowModel Model
        {
            get { return model; }
            set { SetProperty(ref model, value); }
        }
        //ControlEnable
        private EnableControl controlEnable;

        public EnableControl ControlEnable
        {
            get { return controlEnable; }
            set { SetProperty(ref controlEnable, value); }
        }
        //Communication Interface
        private static Abstract_Communication communication;
        //Title
        private string title = "CL_VisionCommunication_Test";

        public string Title
        {
            get { return title; }
            set { SetProperty(ref title, value); }
        }

        private string status="";

        public string Status
        {
            get { return status; }
            set { SetProperty(ref status , value); }
        }

        //ManagerList
        private List<string> managersCount=new List<string>();

        public List<string> ManagersCount
        {
            get { return managersCount; }
            set { SetProperty(ref managersCount, value); }
        }
        //Communication Parameters
        private List<CommunicationParameters> allParameters=new List<CommunicationParameters>();

        public List<CommunicationParameters> AllParameters
        {
            get { return allParameters; }
            set { SetProperty(ref allParameters,value);}
        }

        private CommunicationParameters _objectItemsList;

        public CommunicationParameters ObjectItemsList
        {
            get { return _objectItemsList; }
            set {SetProperty(ref  _objectItemsList, value);  }
        }


        private bool _tcpIP;

        public bool TcpIP
        {
            get { return _tcpIP; }
            set { SetProperty(ref _tcpIP, value); }
        }
        private bool _modbus;

        public bool Modbus
        {
            get { return _modbus; }
            set { SetProperty(ref _modbus, value); }
        }


        private ObjectItems _itemsValue;

        public ObjectItems ItemsValue
        {
            get { return _itemsValue; }
            set { SetProperty(ref  _itemsValue, value); }
        }

        public ICommand OutputsCommand { get; private set; }

        public DelegateCommand<string> ModelChangeCommand { get; private set; }

        private DelegateCommand<string> managerChangedCommand;

        public DelegateCommand<string> ManagerChangedCommand
        {
            get { return managerChangedCommand; }
            set { SetProperty(ref managerChangedCommand, value); }
        }

        private DelegateCommand configCommand;

        public DelegateCommand ConfigCommand
        {
            get { return configCommand; }
            set { configCommand = value; }
        }

        private DelegateCommand<string> slaverInfo;

        public DelegateCommand<string> SlaverInfo
        {
            get { return slaverInfo; }
            set { slaverInfo = value; }
        }

        private DelegateCommand getStatus;

        public DelegateCommand GetStatus
        {
            get { return getStatus; }
            set { getStatus = value; }
        }

        private ICommand changeItemDataCommand;

        public ICommand ChangeItemDataCommand
        {
            get { return changeItemDataCommand; }
            set { SetProperty(ref changeItemDataCommand, value); }
        }

        private ICommand sendObjectDataCommand;

        public ICommand SendObjectDataCommand 
        {
            get { return sendObjectDataCommand; }
            set { SetProperty(ref sendObjectDataCommand, value); }
        }

        private ICommand requestObjectDataCommand;

        public ICommand RequestObjectDataCommand
        {
            get { return requestObjectDataCommand; }
            set { SetProperty(ref requestObjectDataCommand, value); }
        }
        #region  SlaveCommand
        private DelegateCommand<object> seqPoint;

        public DelegateCommand<object> SeqPoint
        {
            get { return seqPoint; }
            set { seqPoint = value; }
        }

        private DelegateCommand<string> lastJobChangedCommand;

        public DelegateCommand<string> LastJobChangedCommand
        {
            get { return lastJobChangedCommand; }
            set { SetProperty(ref lastJobChangedCommand, value);}
        }

        private DelegateCommand<object> runStateChangedCommand;

        public DelegateCommand<object> RunStateChangedCommand
        {
            get { return runStateChangedCommand; }
            set { SetProperty(ref runStateChangedCommand, value); }
        }

        private DelegateCommand<string> resultStateChangedCommand;

        public DelegateCommand<string> ResultStateChangedCommand
        {
            get { return resultStateChangedCommand; }
            set { SetProperty(ref resultStateChangedCommand, value); }
        }

        private DelegateCommand<string> aliveStateChangedCommand;

        public DelegateCommand<string> AliveStateChangedCommand
        {
            get { return aliveStateChangedCommand; }
            set { SetProperty( ref aliveStateChangedCommand, value); }
        }

        private DelegateCommand<string> operationModeChangedCommand;

        public DelegateCommand<string> OperationModeChangedCommand
        {
            get { return operationModeChangedCommand; }
            set { SetProperty(ref operationModeChangedCommand, value); }
        }

        private DelegateCommand<object> selectPlatformChangedCommand;

        public DelegateCommand<object> SelectPlatformChangedCommand
        {
            get { return selectPlatformChangedCommand; }
            set { SetProperty(ref selectPlatformChangedCommand, value); }
        }

        public ICommand SlaveCommand { get; private set; }
        #endregion

        #region  MasterCommand

        #endregion

        #endregion

        #region Executor
        public MainWindowViewModel()
        {
            model = new MainWindowModel();
            ControlEnable = new EnableControl();
            InitialCommand();
        }

        private void InitialCommand()
        {
            ModelChangeCommand = new DelegateCommand<string>(SelectModeState);
            LoadINICommand = new DelegateCommand(LoadINI);
            LastJobChangedCommand = new DelegateCommand<string>(OnLastJob);
            OutputsCommand = new MultiParameterCommand<object>(OnOutputCommand);
            ManagerChangedCommand = new DelegateCommand<string>(OnManagerChange);
            RunStateChangedCommand = new DelegateCommand<object>(OnRunStateCommand);
            ResultStateChangedCommand = new DelegateCommand<string>(OnResultStateCommand);
            AliveStateChangedCommand = new DelegateCommand<string>(OnAliveStateCommand);
            OperationModeChangedCommand=new DelegateCommand<string>(OnOperationModeCommand);
            ChangeItemDataCommand = new MultiParameterCommand<object>(OnChangeItemData);
            SendObjectDataCommand = new MultiParameterCommand<object>(OnSendObjectDataCommand);
            RequestObjectDataCommand = new MultiParameterCommand<object>(OnRequestObjectDataCommand);
            ConfigCommand = new DelegateCommand(OnConfigCommand);
            GetStatus = new DelegateCommand(OnGetStatus);
            SlaverInfo = new DelegateCommand<string>(OnSlaverInfo);
            SelectPlatformChangedCommand = new DelegateCommand<object>(OnSelectPlatformCommand);
            SeqPoint = new DelegateCommand<object>(OnSeqPoint);
            SlaveCommand = new MultiParameterCommand<object>(OnSlaveCommand);
        }

        private void SelectModeState(string para)
        {
            if (para == "Master" || para == "Slave")
            {
                ControlEnable.EnableModel = false;
                ControlEnable.EnableLoad = true;
                commnuMode = para == "Master" ? 1 : 2;
            }
        }

        public DelegateCommand LoadINICommand { get; private set; }       

        private void LoadINI()
        {
            Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog();
            openFileDialog.Filter = "通讯配置文件 (*.cdat)|*.cdat";
            openFileDialog.Title = "选择Cdat文件";
            if (openFileDialog.ShowDialog() == true)
            {
                configFilePath = openFileDialog.FileName;
                Title +="___"+ configFilePath;
                try
                {
                    string fileContent = System.IO.File.ReadAllText(configFilePath);
                    int Error = 0;
                    CommuConfiguration.LoadIni(configFilePath, out Error);
                    if (Error != 0)
                        MessageBox.Show("读取文件失败", "文件");
                    else
                    {
                        SetControlState();
                        ManagersCount=GetManagers();
                        AllParameters = CommuConfiguration.GetParameters();
                        InitCommu(configFilePath);
                    }
                }
                catch
                {
                    MessageBox.Show("读取文件失败", "文件");
                }
            }
        }
        #endregion

        #region 内部使用 私有化
        private void SetControlState()
        {
            if (commnuMode == 1)
            {
                ControlEnable.EnableOutputs = true;
                ControlEnable.EnableStates = false;
            }
            if (commnuMode == 2)
            {
                ControlEnable.EnableOutputs = false;
                ControlEnable.EnableStates = true;
                ControlEnable.EnableControlCommu=true;
            }
        }

        private List<string> GetManagers()
        {
            List<string> managersName = new List<string>();
            try
            {
                int count = Convert.ToInt32(CommuConfiguration.GetValueByPath("Root.Global.ObjectManagers", out int Errocode));
                if (Errocode == 0)
                {
                    for (int i = 0; i < count; i++)
                    {
                        managersName.Add("ObjectManager" + i.ToString() + "-Interface0");
                    }
                }
            }
            catch (Exception)
            {
                MessageBox.Show("GetObjectManagers Error","Error");
            }
            return managersName;
        }

        private void OnOutputCommand(object obj)
        {
            try
            {
                if (TsPlatForm)
                {
                    ///TS具体类实现           
                    if (obj is Object[] array)
                    {
                        string name = array[0].ToString();
                        managerNameIndex = int.Parse(array[1].ToString().Substring(13, 1));
                        double para1 = double.Parse(array[2].ToString());
                        double para2 = double.Parse(array[3].ToString());
                        switch (name)
                        {
                            case "StartMeasure":
                                communication.SendConstantValue(managerNameIndex, "Command", 1);
                                communication.SendConstantValue(managerNameIndex, "Para1", para1);
                                communication.SendConstantValue(managerNameIndex, "Para2", para2);
                                communication.SendConstantValue(managerNameIndex, "StartSingle", 1);
                                Thread.Sleep(20);
                                communication.SendConstantValue(managerNameIndex, "StartSingle", 0);
                                break;
                            case "ChangeProg":
                                communication.SendConstantValue(managerNameIndex, "Command", 2);
                                communication.SendConstantValue(managerNameIndex, "Para1", para1);
                                communication.SendConstantValue(managerNameIndex, "Para2", para2);
                                communication.SendConstantValue(managerNameIndex, "StartSingle", 1);
                                Thread.Sleep(20);
                                communication.SendConstantValue(managerNameIndex, "StartSingle", 0);
                                break;
                            case "Reset":
                                communication.SendConstantValue(managerNameIndex, "Command", 3);
                                communication.SendConstantValue(managerNameIndex, "Para1", para1);
                                communication.SendConstantValue(managerNameIndex, "Para2", para2);
                                communication.SendConstantValue(managerNameIndex, "StartSingle", 1);
                                Thread.Sleep(20);
                                communication.SendConstantValue(managerNameIndex, "StartSingle", 0);
                                break;
                            case "StartCalib":
                                communication.SendConstantValue(managerNameIndex, "Command", 5);
                                communication.SendConstantValue(managerNameIndex, "Para1", para1);
                                communication.SendConstantValue(managerNameIndex, "Para2", para2);
                                communication.SendConstantValue(managerNameIndex, "StartSingle", 1);
                                Thread.Sleep(20);
                                communication.SendConstantValue(managerNameIndex, "StartSingle", 0);
                                break;
                            case "CheckCalib":
                                MessageBox.Show("暂无此功能");
                                break;
                            case "Special":
                                communication.SendConstantValue(managerNameIndex, "Command", 8);
                                communication.SendConstantValue(managerNameIndex, "Para1", para1);
                                communication.SendConstantValue(managerNameIndex, "Para2", para2);
                                communication.SendConstantValue(managerNameIndex, "StartSingle", 1);
                                Thread.Sleep(20);
                                communication.SendConstantValue(managerNameIndex, "StartSingle", 0);
                                break;
                            case "SeqPoint":
                                if (para2 >= 0  && para1 >= 0 && para1 <= 7)
                                    communication.SendConstantValue(managerNameIndex, "HandShake0" + para1.ToString(), para2);
                                else
                                    MessageBox.Show("参数不正确，无法执行！！！");
                                break;
                            default:
                                break;
                        }
                    }
                }
                else
                {
                    //NC具体类实现
                    if (obj is Object[] array)
                    {
                        string name = array[0].ToString();
                        switch (name)
                        {
                            case "Start Check":
                                communication.SendConstantValue(managerNameIndex, "Start check", array[1].ToString().ToUpper()=="TRUE"?1:0, false);
                                break;
                            case "Execute Command":                              
                                communication.SendConstantValue(managerNameIndex, "Execute command", array[1].ToString().ToUpper() == "TRUE" ? 1 : 0, false);
                                break;
                            case "HandShake":
                                //double para2 = double.Parse(array[1].ToString());
                                communication.SendConstantValue(managerNameIndex, "IHandshake"+ array[1].ToString(), double.Parse(array[2].ToString()), false);
                                break;
                            case "Command Code":
                                communication.SendConstantValue(managerNameIndex, "Command code", double.Parse(array[1].ToString()), false);
                                break;
                            case "Command Parameter":
                                communication.SendConstantValue(managerNameIndex, "Command parameter", double.Parse(array[1].ToString()), false);
                                break;
                            case "NCGetState":
                                Status= communication.GetStatus(managerNameIndex);
                                break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message,"Error");
            }
        }

        private void OnManagerChange(string Name)
        {
            if(!string.IsNullOrEmpty(Name))
                managerNameIndex = int.Parse(Name.Substring(13, 1));
        }

        private void OnRunStateCommand(object State)
        {
            try
            {
                switch (State)
                {
                    case "Invalid":
                        communication.SendConstantValue(managerNameIndex, "RunStates", 0);
                        break; ;
                    case "SystemRunning":
                        communication.SendConstantValue(managerNameIndex, "RunStates", 1);
                        break;
                    case "SystemError":
                        communication.SendConstantValue(managerNameIndex, "RunStates", 2);
                        break;
                    case "TestplanLoaded":
                        communication.SendConstantValue(managerNameIndex, "TestplanStates", 3);
                        break;
                    case "TestplanReady":
                        communication.SendConstantValue(managerNameIndex, "TestplanStates", 4);
                        break;
                    case "TestplanRunning":
                        communication.SendConstantValue(managerNameIndex, "TestplanStates", 5);
                        break;
                    case "TestplanWaitForData":
                        communication.SendConstantValue(managerNameIndex, "TestplanStates", 6);
                        break;
                    case "TestplanFinished":
                        communication.SendConstantValue(managerNameIndex, "TestplanStates", 7);
                        break;
                    case "TestplanPause":
                        break;
                    case "TestplanBreakPoint":
                        break;
                    case "TestplanStepPause":
                        break;
                    case "TestplanDelayed":
                        communication.SendConstantValue(managerNameIndex, "TestplanStates", 12);
                        break;
                    default:
                        break;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void OnResultStateCommand(string str)
        {
            try
            {
                switch (str)
                {
                    case "Invalid":
                        communication.SendConstantValue(managerNameIndex, "ResultStates", 0);
                        break;
                    case "Undefined":
                        communication.SendConstantValue(managerNameIndex, "ResultStates",1);
                        break;
                    case "Error":
                        communication.SendConstantValue(managerNameIndex, "ResultStates", 2);
                        break;
                    case "Passed":
                        communication.SendConstantValue(managerNameIndex, "ResultStates", 3);
                        break;
                    case "Failed":
                        communication.SendConstantValue(managerNameIndex, "ResultStates", 4);
                        break;
                    default:
                        break;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void OnAliveStateCommand(string str)
        { 
        }

        private void OnOperationModeCommand(string str)
        { 
        }

        private void OnLastJob(string str)
        { }

        private void OnChangeItemData(object obj)
        {
            if (obj is Object[] array)
            {
                string itemName = array[0].ToString();
                string value = array[1].ToString();
                int index = int.Parse(array[2].ToString());
                ItemsValue.Items[index].Name = itemName;
                ItemsValue.Items[index].Default = value;
            }
        }

        private void OnSendObjectDataCommand(object obj)
        {
            if (obj is Object[] array)
            {
                string itemName = array[0].ToString();
                int index = int.Parse(array[1].ToString());
                communication.SendObjectValue(managerNameIndex, _itemsValue);
            }
        }

        private void OnRequestObjectDataCommand(object obj) 
        {
            if (obj is Object[] array)
            {
                string itemName = array[0].ToString();
                int index = int.Parse(array[1].ToString());
                List<string> list=communication.ReadObjectValue(managerNameIndex, _itemsValue);
                for (int i = 0; i < list.Count; i++)
                {
                    ItemsValue.Items[i].Default = list[i];
                }
            }
        }

        private void OnConfigCommand()
        {
            try
            {
                if(!string.IsNullOrEmpty(configFilePath))
                    Process.Start(configFilePath);
            }
            catch (Exception)
            {
                MessageBox.Show("请选择正确的文件！！！");
            }
        }

        private void OnGetStatus()
        {
            try
            {
                Status = communication.GetStatus(managerNameIndex);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void OnSlaverInfo(string str)
        {
            if (!string.IsNullOrEmpty(configFilePath))
            {
                string file= AppDomain.CurrentDomain.BaseDirectory+ "\\"+str;
                FileInfo fileInfo = new FileInfo(file);
                if (fileInfo.Exists)
                {
                    SlaveDllInfo info = new SlaveDllInfo();
                    string fileName = "FileName: "+fileInfo.Name+"\r\n";
                    string fileSize = "FileSize: "+fileInfo.Length.ToString() + "\r\n";
                    string creationTime ="CreateTime: "+ fileInfo.CreationTime.ToString() + "\r\n";
                    string lastWriteTime ="LastWriteTime: "+ fileInfo.LastWriteTime.ToString() + "\r\n";
                    string lastAccessTime ="LastAccessTime"+ fileInfo.LastAccessTime.ToString() + "\r\n";
                    string fileExtension ="Extension: "+ fileInfo.Extension;
                    string directoryName = "DirectoryName: " + fileInfo.DirectoryName;                   
                    info.SetInfo(fileName+ fileSize+ creationTime+ lastWriteTime+ lastAccessTime+ fileExtension+ directoryName);
                    info.ShowDialog();
                }
            }
        }

        private void OnSelectPlatformCommand(object select)
        {
            TsPlatForm = (bool)select;
        }

        private void OnSeqPoint(object obj)
        {
            try
            {
                if (obj is Object[] array)
                {
                    int point = int.Parse(array[0].ToString());
                    bool ret = bool.Parse(array[1].ToString());
                    managerNameIndex = int.Parse(array[2].ToString().Substring(13, 1));
                    if (point >= 0 && point <= 7)
                        communication.SendConstantValue(managerNameIndex, "HandShake0" + point.ToString(), ret == true ? 1 : 0);
                }
            }
            catch (Exception)
            {
            }
        }

        private void OnSlaveCommand(object obj)
        {
            if (obj is Object[] array)
            {
                string name = array[0].ToString();
                switch (name)
                {
                    case "System Alive":
                        communication.SendConstantValue(managerNameIndex, "System alive", array[1].ToString().ToUpper() == "TRUE" ? 1 : 0, false);
                        break;
                    case "Automatic Mode Ready":
                        communication.SendConstantValue(managerNameIndex, "Automatic mode ready", array[1].ToString().ToUpper() == "TRUE" ? 1 : 0, false);
                        break;
                    case "System Ready":
                        communication.SendConstantValue(managerNameIndex, "System ready", array[1].ToString().ToUpper() == "TRUE" ? 1 : 0, false);
                        break;
                    case "Data Valid":
                        communication.SendConstantValue(managerNameIndex, "Data valid", array[1].ToString().ToUpper() == "TRUE" ? 1 : 0, false);
                        break;
                    case "Check Routine Result O.K":
                        communication.SendConstantValue(managerNameIndex, "Check routine result O.K", array[1].ToString().ToUpper() == "TRUE" ? 1 : 0, false);
                        break;
                    case "Check Routine Result n.O.K":
                        communication.SendConstantValue(managerNameIndex, "Check routine result n.O.K", array[1].ToString().ToUpper() == "TRUE" ? 1 : 0, false);
                        break;
                    case "Self Test Failed":
                        communication.SendConstantValue(managerNameIndex, "Self test failed", array[1].ToString().ToUpper() == "TRUE" ? 1 : 0, false);
                        break;
                    case "Event Log Full":
                        communication.SendConstantValue(managerNameIndex, "Event log full", array[1].ToString().ToUpper() == "TRUE" ? 1 : 0, false);
                        break;
                    case "HandShake":
                        communication.SendConstantValue(managerNameIndex, "OHandShake0"+ array[1].ToString(),double.Parse(array[2].ToString()), false);
                        break;
                    case "Current Check Routine ID":
                        communication.SendConstantValue(managerNameIndex, "Current check routine ID", double.Parse(array[1].ToString()), false);
                        break;
                    case "Current Security Profile ID":
                        communication.SendConstantValue(managerNameIndex, "Current security profile ID", double.Parse(array[1].ToString()), false);
                        break;
                    case "Last Command Code":
                        communication.SendConstantValue(managerNameIndex, "Last command code", double.Parse(array[1].ToString()), false);
                        break;
                    case "GetState":
                        Status= communication.GetStatus(managerNameIndex);
                        break;
                    default:
                        break;

                }
            }
        }
        #endregion

        #region Communication
        private void InitCommu(string Path)
        {
            ConnectedString = "";
            if (commnuMode == 1)
            {

                if (TcpIP)
                {
                    //客户端
                    communication = new TcpIPClient_Communication();
                    ConnectedString = communication.Init(Path, TsPlatForm ? "TS" : "NC");
                }
                else if(Modbus)
                {
                    communication = new Master_Communication();
                    ConnectedString = communication.Init(Path, TsPlatForm ? "TS" : "NC");

                }
            }
            if (commnuMode == 2)
            {


                communication = new Slave_Communication();
                ConnectedString = communication.Init(Path, TsPlatForm ? "TS" : "NC");



            }
            if (connectedstring.Contains("False"))
            {
                MessageBox.Show("通讯初始化失败", "报警提示");
            }
        }
        #endregion
    }
}
